import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ObjectUtil} from '../../../utils/object-util';
import {DhlCommonInputComponent} from '../dhlCommonInput';

@Component({
  selector: 'dhl-tree',
  templateUrl: './dhl-tree.component.html'
})
export class DhlTreeComponent extends DhlCommonInputComponent implements OnInit {

  nodes;
  checkedKeys;
  joinDomain;
  @Input() expandKeys = [];
  @Input() isMultiple = false;
  @Input() expandAll = false;
  @Input() isCheck = false;
  @Input() rootCode;
  @Input() options;
  @Input() placeholder;
  @Input() nzErrorTip;
  @Input() onExpand;
  @Input() drag = true;
  @Input() maxHeight = 400;


  @Input()
  set domain(domain) {
    this.joinDomain = domain;
  }

  @Input()
  set treeData(value) {
    if (ObjectUtil.isHaveValue(value)) {
      value.forEach((item) => {
        this.expandKeys.push(item.key);
      });
      this.nodes = value.map(p => {
        if (p.key) {
          return p;
        } else {
          return {...p, key: p.code};
        }
      });
    }
  };

  @Output() nodeClick = new EventEmitter();


  ngOnInit() {

    $('[dhl-input-element]', this.inputControl.nativeElement).attr('isArray', 'true');

    setTimeout(() => {
      if (this.maxHeight) {
        const o = $('ul.ant-tree.ant-tree-icon-hide.draggable-tree', $(this.inputControl.nativeElement));
        o.css('max-height', this.maxHeight + 'px');
        o.css('overflow-y', 'scroll');
      }
    }, 100);

    const interval = setInterval(() => {
      if (this.rootCode) {
        clearInterval(interval);
        this.loadTreeData();
      } else {
        this.checkedKeys = this.value;
      }
    }, 10);
  }

  click({keys}) {
    if (this.rootCode) {
      const checkedData = this.getDataByCode(keys);
      if (this.isCheck) {
        this.nodeClick.emit(checkedData);
      } else {
        this.value = this.getTreeIds(checkedData);
        this.valueChange.emit(checkedData);
      }
    } else {
      this.value = keys;
      this.valueChange.emit(keys);
    }
  }

  checkChange({keys}) {
    if (this.rootCode) {
      const checkedData = this.getDataByCode(keys);
      this.value = this.getTreeIds(checkedData);
      this.valueChange.emit(checkedData);
    } else {
      this.value = keys;
      this.valueChange.emit(keys);
    }
  }


  getTreeIds(nodes) {
    if (ObjectUtil.isHaveValue(nodes)) {
      return nodes.map(p => p.id);
    }
  }


  getDataByCode(keys) {
    return keys
      .filter(p => ObjectUtil.isHaveValue(p))
      .map(p => {
        return this.findByCode(p, this.nodes[0], 'code');
      });
  }

  getNodeCodeById(keys) {
    return this.getNodeDataById(keys).map(p => p.code);
  }


  getNodeDataById(keys) {
    if (ObjectUtil.isHaveValue(keys)) {
      return keys
        .filter(p => ObjectUtil.isHaveValue(p))
        .map(p => this.findByCode(p, this.nodes[0], 'id'));
    } else {
      return [];
    }
  }


  findByCode(targetCode, parentNode, field) {

    if (parentNode[field] == targetCode) {
      parentNode.fatherLine = [parentNode];
      return parentNode;
    }

    if (parentNode.children) {
      for (const child  of parentNode.children) {
        const n = this.findByCode(targetCode, child, field);
        if (n) {
          if (n.fatherLine) {
            n.fatherLine.push(parentNode);
          } else {
            n.fatherLine = [parentNode];
          }
          return n;
        }
      }
    } else {
      return;
    }
  }

  dealReturnChildren(topNodes) {
    if (topNodes) {
      for (const node of topNodes) {
        node.key = node.code;
        node.isLeaf = node.leaf;
        if (node.children) {
          this.dealReturnChildren(node.children);
        }
      }
    }
  }

  fresh() {
    this.inputValue = [];
    this.loadTreeData();
  }

  loadTreeData() {

    this.requestService.get(`tree/root/${this.rootCode}`, {joinDomain: this.joinDomain}).subscribe(rootdata => {
      if (rootdata) {
        rootdata.key = rootdata.code;
        rootdata.isLeaf = rootdata.leaf;
        this.requestService
          .get(`tree/children`, {joinDomain: this.joinDomain, pcode: this.rootCode, treeIds: this.inputValue})
          .subscribe(data => {
            if (data) {
              this.dealReturnChildren(data);
              rootdata.expanded = true;
              rootdata.children = data;
            } else {
              rootdata.expanded = false;
            }
            this.nodes = [rootdata];
            this.checkedKeys = this.getNodeCodeById(this.inputValue) || [];
          });
      } else {
        this.nodes = [{code: this.rootCode, title: 'root', isLeaf: true}];
      }
    });
  }


  onDrop(obj) {
    const dragPos = obj.node.component.dragPos;
    const targetKey = obj.node.key;
    const dragKey = obj.dragNode.key;
    this.requestService.post(`tree/changesort`, {pos: dragPos, targetCode: targetKey, dragCode: dragKey}).subscribe();
  }

  expand(event) {
    if (event.eventName === 'expand') {
      const {node, keys} = event;
      if (node && node.key && node.getChildren().length === 0 && node.isExpanded) {
        if (this.onExpand) {
          this.onExpand(node);
        } else {
          this.requestService.get(`tree/children`, {pcode: node.key, joinDomain: this.joinDomain}).subscribe(data => {
            if (data) {
              node.addChildren(data.map(p => ({...p, key: p.code, isLeaf: p.leaf})));
            }
          });
        }
      }
    }
  }


}


